/*-------------------------------------------------------------------------
 *
 * standby.h
 *	  热备份模式的定义。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/storage/standby.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef STANDBY_H
#define STANDBY_H

#include "datatype/timestamp.h"
#include "storage/lock.h"
#include "storage/procsignal.h"
#include "storage/relfilenode.h"
#include "storage/standbydefs.h"

/* 用户可设置的 GUC 参数 */
extern PGDLLIMPORT int vacuum_defer_cleanup_age;
extern PGDLLIMPORT int max_standby_archive_delay;
extern PGDLLIMPORT int max_standby_streaming_delay;
extern PGDLLIMPORT bool log_recovery_conflict_waits;

extern void InitRecoveryTransactionEnvironment(void);
extern void ShutdownRecoveryTransactionEnvironment(void);

extern void ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid,
												RelFileNode node);
extern void ResolveRecoveryConflictWithSnapshotFullXid(FullTransactionId latestRemovedFullXid,
													   RelFileNode node);
extern void ResolveRecoveryConflictWithTablespace(Oid tsid);
extern void ResolveRecoveryConflictWithDatabase(Oid dbid);

extern void ResolveRecoveryConflictWithLock(LOCKTAG locktag, bool logging_conflict);
extern void ResolveRecoveryConflictWithBufferPin(void);
extern void CheckRecoveryConflictDeadlock(void);
extern void StandbyDeadLockHandler(void);
extern void StandbyTimeoutHandler(void);
extern void StandbyLockTimeoutHandler(void);
extern void LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start,
								TimestampTz cur_ts, VirtualTransactionId *wait_list,
								bool still_waiting);

/*
 * 备用 Rmgr (RM_STANDBY_ID)
 *
 * 备用恢复管理器存在是为了执行使热备用正常工作的操作。
 * 包括记录由事务和运行事务快照所占用的 AccessExclusiveLocks。
 */
extern void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid);
extern void StandbyReleaseLockTree(TransactionId xid,
								   int nsubxids, TransactionId *subxids);
extern void StandbyReleaseAllLocks(void);
extern void StandbyReleaseOldLocks(TransactionId oldxid);

#define MinSizeOfXactRunningXacts offsetof(xl_running_xacts, xids)


/*
 * GetRunningTransactionData() 的声明。类似于快照，但
 * 不是完全相同。这与该服务器上的可见性无关，
 * 因此这与 snapmgr.c 和 snapmgr.h 完全分开。
 * 此数据对于在备用服务器上创建初始快照状态很重要。
 * 我们需要比普通快照更多的信息，因此我们为我们的需求
 * 使用特定的数据结构。此数据在每个
 * 检查点之后立即作为单独记录写入 WAL。
 * 这意味着无论我们从哪里启动备用，我们几乎都会立即看到
 * 我们需要的数据来开始执行查询。
 */

typedef enum
{
	SUBXIDS_IN_ARRAY,			/* xids 数组包括所有正在运行的 subxids */
	SUBXIDS_MISSING,			/* 快照溢出，subxids 缺失 */
	SUBXIDS_IN_SUBTRANS,		/* subxids 不包括在 'xids' 中，但
								 * pg_subtrans 完全是最新的 */
} subxids_array_status;

typedef struct RunningTransactionsData
{
	int			xcnt;			/* xids[] 中的事务 ID 数量 */
	int			subxcnt;		/* xids[] 中的子事务 ID 数量 */
	subxids_array_status subxid_status;
	TransactionId nextXid;		/* 来自 ShmemVariableCache->nextXid 的 xid */
	TransactionId oldestRunningXid; /* *不是* oldestXmin */
	TransactionId latestCompletedXid;	/* 因此我们可以设置 xmax */

	TransactionId *xids;		/* 仍在运行的 (sub)xids 的数组 */
} RunningTransactionsData;

typedef RunningTransactionsData *RunningTransactions;

extern void LogAccessExclusiveLock(Oid dbOid, Oid relOid);
extern void LogAccessExclusiveLockPrepare(void);

extern XLogRecPtr LogStandbySnapshot(void);
extern void LogStandbyInvalidations(int nmsgs, SharedInvalidationMessage *msgs,
									bool relcacheInitFileInval);

#endif							/* STANDBY_H */
